/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package au.edu.swin.unilearn;

import au.edu.swin.unilearn.subject.*;
import au.edu.swin.unilearn.assignment.*;
import au.edu.swin.unilearn.students.*;
import au.edu.swin.unilearn.submission.*;
import au.edu.swin.unilearn.tutorialGroup.*;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJB;
import javax.faces.model.SelectItem;
import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.myfaces.custom.fileupload.UploadedFile;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import java.security.MessageDigest;
//import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

/**
 *
 * @author DidierLeung
 */
public class SubmissionManagedBean
{
    @EJB
    private SubjectSessionRemote subjectSession;
    @EJB
    private AssignmentSessionRemote assignmentSession;
    @EJB
    private StudentSessionRemote studentSession;
    @EJB
    private SubmissionSessionRemote submissionSession;
//    @EJB
//    private TutorialGroupSessionRemote tutorialGroupSession;
    private String filterSubjectCode;
    private String filterAssignmentNo;
    private UploadedFile submissionFile;
    //private String assignmentFile;
    private String studentID;
    private String studentPassword;
    private Boolean statementAgree;
    private String submittedDateStr;
    private String errorMessage;
    private String args;
    private Integer submissionNo;
    private String myResult;

//    public List<StudentTutorialGroup> getAllStudentTutorialGroup()
//    {
//        return studentTGSession.getAllStudentTutorialGroups();
//    }
//
    //OK
    public List<Subject> getSubjectCodeEnrolled()
    {
        List<Subject> enrolledSubjects = new ArrayList();
        List<TutorialGroup> tutorialsEnrolled = studentSession.getEnrolledTutorialGroups(args);
        for (int i = 0; i < tutorialsEnrolled.size(); i++)
        {
            enrolledSubjects.add((tutorialsEnrolled.get(i)).getSubject());
//            System.out.println("Subject Code: " + ((tutorialsEnrolled.get(i)).getSubject()).getSubject_code() +
//                               " & Name: " + ((tutorialsEnrolled.get(i)).getSubject()).getSubject_name());
        }
        return enrolledSubjects;
    }

    //OK
    public List<SelectItem> getSubjectCodeItems()
    {
        List<SelectItem> subjectCodeItems = new ArrayList();
        for (Subject s : getSubjectCodeEnrolled())
        {
            SelectItem si = new SelectItem(s.getSubject_code(), s.getSubject_code() + " - " + s.getSubject_name());
            subjectCodeItems.add(si);
//            System.out.println("Student ID: " + stg.getStudentID() +
//                               " enrolled in " + stg.getSubjectCode() + "-" + aSubject.getSubject_name());
        }
        return subjectCodeItems;
    }

    //OK
    public void setFilterSubjectCode(String filterSubjectCode)
    {
//        System.out.println("FILTER SUBJECT CODE (SET 1): " + filterSubjectCode);
        this.filterSubjectCode = filterSubjectCode;
//        System.out.println("FILTER SUBJECT CODE (SET 2): " + getFilterSubjectCode());
    }

    //OK
    public String getFilterSubjectCode()
    {
//        System.out.println("FILTER SUBJECT CODE FROM getMethod: " + filterSubjectCode);
        return filterSubjectCode;
    }

    //OK
    public String checkSubmissionOpen()
    {
        List openSubmission = getAssignmentForSubjectCode();
        if (openSubmission.size() == 0)
        {
            return "noSubmissionOpen";
        }
        else
        {
            return "display";
        }
    }

    public String getSubject()
    {
//        System.out.println("Get Subject for title");
//        System.out.println(getFilterSubjectCode());
        Subject aSubject = subjectSession.getSubject(getFilterSubjectCode());
        return aSubject.getSubject_code() + "-" + aSubject.getSubject_name();
    }

    public List<Assignment> getAssignmentForSubjectCode()
    {
        return assignmentSession.getAssignments(getFilterSubjectCode());
    }

    public String getFilterAssignmentNo()
    {
        return filterAssignmentNo;
    }

    public List<SelectItem> getAssignmentNoItems()
    {
        List<SelectItem> assignmentNoItems = new ArrayList();
        for (Assignment ass : getAssignmentForSubjectCode())
        {
            SelectItem si = new SelectItem(ass.getAssignment_no(),
                                           ass.getAssignment_no() + "-" + ass.getAssignment_name());
            assignmentNoItems.add(si);
        }
        return assignmentNoItems;
    }

    public void setFilterAssignmentNo(String filterAssignmentNo)
    {
        this.filterAssignmentNo = filterAssignmentNo;
    }

    public String checkInput()
    {
        if (!this.studentID.equals(args))
        {
            errorMessage = "Invalid Student ID or Password";
            return "fail";
        }
        //Check if studentid and password match
        if (!studentSession.checkPassword(this.studentID, this.studentPassword))
        {
            errorMessage = "Invalid Student ID or Password";
            return "fail";
        }

        if (!this.statementAgree)
        {
            errorMessage = "Assignment Agreement Not selected";
            return "fail";
        }
        //Check if file exist
        //TO BE DONE LATER
//        File uploadFile = new File("C:/Users/DidierLeung/Desktop/BookEntryForm.jsp");
//        System.out.println(uploadFile.exists());
//        if(!uploadFile.exists())
//        {
//            errorMessage = "File does not exist.";
//            return "fail";
//        }
        if (!processSubmissionFile())
        {
            errorMessage = "Error in computing Checksum for your submission";
            return "fail";
        }

        //Save All data to database
        Calendar cal = Calendar.getInstance(TimeZone.getDefault());
        Date submittedDate = cal.getTime();
        String dateFormat = "dd-MM-yyyy HH:mm:ss";
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        sdf.setTimeZone(TimeZone.getDefault());
        submittedDateStr = sdf.format(cal.getTime());


        try
        {
            String fileOnServerURL = saveSubmissionToServer();
            if(fileOnServerURL != null)
            {
                Assignment assignmentObj = assignmentSession.getAssignment(
                        filterAssignmentNo, filterSubjectCode);
                Student aStudent = studentSession.getStudent(args);

                submissionNo = submissionSession.isAlreadySubmitted(
                        filterAssignmentNo, filterSubjectCode, args);
                //Check if student already made a submission before
                if (submissionNo == null)
                {
                    Submission aSubmission =
                            new Submission(null, submittedDate, fileOnServerURL, 0.0, null, "Unmarked",
                                           assignmentObj, aStudent);
                    submissionNo = submissionSession.addSubmission(aSubmission);
                }
                else
                {
                    Submission aSubmission = submissionSession.getSubmission(submissionNo);
                    File oldFile = new File(aSubmission.getSubmission_file_url());
                    oldFile.delete();
                    aSubmission.setSubmission_file_url(fileOnServerURL);
                    aSubmission.setSubmitted_date(submittedDate);
                    submissionSession.updateSubmission(aSubmission);
                }
                return "success";
            }
            else
            {
                return "fail";
            }
        }
        catch (Exception e)
        {
            return "fail";
        }

    }
    
    private String saveSubmissionToServer()
    {
        try
        {
            File newFile = new File(submissionFile.getName());
            String rootFileSystem = "Unilearn_Storage/" + filterSubjectCode + 
                                 "/Submission/TutorialGroup_" + getActivityNo()+ "/Assignment_" + filterAssignmentNo;
            String fileOnServerURL = rootFileSystem + "/" + args + "_" + newFile.getName();
            InputStream in = submissionFile.getInputStream();
            OutputStream out = new FileOutputStream(fileOnServerURL);

            // Transfer bytes from in to out
            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0)
            {
                out.write(buf, 0, len);
            }
            in.close();
            out.close();
            return fileOnServerURL;
        }
        catch (IOException ex)
        {
            Logger.getLogger(SubmissionManagedBean.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }

    public Boolean processSubmissionFile()
    {
        try
        {
            MessageDigest md = MessageDigest.getInstance("MD5");
            InputStream in = new BufferedInputStream(
                    submissionFile.getInputStream());
            try
            {
                byte[] buffer = new byte[64 * 1024];
                int count;
                while ((count = in.read(buffer)) > 0)
                {
                    md.update(buffer, 0, count);
                }
            }
            finally
            {
                in.close();
            }
            byte hash[] = md.digest();
            StringBuffer buf = new StringBuffer();
            for (int i = 0; i < hash.length; i++)
            {
                int b = hash[i] & 0xFF;
                int c = (b >> 4) & 0xF;
                c = c < 10 ? '0' + c : 'A' + c - 10;
                buf.append((char) c);
                c = b & 0xF;
                c = c < 10 ? '0' + c : 'A' + c - 10;
                buf.append((char) c);
            }
            myResult = buf.toString();
            return true;
        }
        catch (Exception x)
        {
            FacesMessage message = new FacesMessage(
                    FacesMessage.SEVERITY_FATAL,
                    x.getClass().getName(), x.getMessage());
            FacesContext.getCurrentInstance().addMessage(
                    null, message);
            return false;
        }
    }

    public String getStudentID()
    {
        return studentID;
    }

    public void setStudentID(String studentID)
    {
        this.studentID = studentID;
    }

    public String getStudentPassword()
    {
        return studentPassword;
    }

    public void setStudentPassword(String studentPassword)
    {
        this.studentPassword = studentPassword;
    }

    public Boolean getStatementAgree()
    {
        return statementAgree;
    }

    public void setStatementAgree(Boolean statementAgree)
    {
        this.statementAgree = statementAgree;
    }

    public UploadedFile getSubmissionFile()
    {
        return submissionFile;
    }

    public String getSubmissionFileStr()
    {
        return submissionFile.getName();
    }

    public void setSubmissionFile(UploadedFile submissionFile)
    {
        this.submissionFile = submissionFile;
    }

    public String getAssignmentName()
    {
        Assignment ass = assignmentSession.getAssignment(this.filterAssignmentNo, this.filterSubjectCode);
        return ass.getAssignment_name();
    }

    public String getDueDate()
    {
        Assignment ass = assignmentSession.getAssignment(this.filterAssignmentNo, this.filterSubjectCode);
        return (ass.getDeadline()).toString();
    }

    public String getActivityNo()
    {
        List<TutorialGroup> tgCollection = studentSession.getEnrolledTutorialGroups(args);
        for (int i = 0; i < tgCollection.size(); i++)
        {
            TutorialGroup tg = tgCollection.get(i);
            Subject s = tg.getSubject();
            if (s.isSubjectCode(filterSubjectCode))
            {
                return (tg.getActivity_no()).toString();
            }
        }
        return null;
    }

    public String getStudentName()
    {
        Student aStudent = studentSession.getStudent(this.studentID);
        return aStudent.getName();
    }

    public String getSubmissionDate()
    {
        return submittedDateStr;
    }

    public String getErrorMessage()
    {
        return errorMessage;
    }

    public String getArgs()
    {
        return args;
    }

    public void setArgs(String args)
    {
        this.args = args;
    }

    public Integer getSubmissionNo()
    {
        return submissionNo;
    }

    public void setSubmissionNo(Integer submissionNo)
    {
        this.submissionNo = submissionNo;
    }

    public String getMyResult()
    {
        return myResult;
    }

    public void setMyResult(String myResult)
    {
        this.myResult = myResult;
    }

//    public List<Assignment> getFilteredAssignmentNos()
//    {
//        List<Assignment> resultList = new ArrayList();
//        for (Assignment ass : getAssignmentForSubjectCode())
//        {
//            Boolean sameNo = true;
//            if (getFilterAssignmentNo() != null &&
//                    !ass.getAssignment_no().equals(getFilterAssignmentNo()))
//            {
//                sameNo = false;
//            }
//
//            if (sameNo)
//            {
//                resultList.add(ass);
//            }
//        }
//        return resultList;
//    }
//
//    public List<StudentTutorialGroup> getFilteredSubjectCodes()
//    {
//        List<StudentTutorialGroup> resultList = new ArrayList();
//        for (StudentTutorialGroup stg : getSubjectCodeEnrolled())
//        {
//            Boolean sameCode = true;
//
//            if (getFilterSubjectCode() != null &&
//                    !stg.getSubjectCode().equals(getFilterSubjectCode()))
//            {
//                sameCode = false;
//            }
//
//            if (sameCode)
//            {
//                resultList.add(stg);
//            }
//        }
//        return resultList;
//    }
//
}
